package com.pdg.islandinterloper.database.objects;

import java.util.List;
import java.util.Random;

import com.pdg.islandinterloper.database.enums.ProfileState;
import com.pdg.islandinterloper.exceptions.IslandPositionGenerationException;

import android.database.Cursor;

public class Profile {
	public static final int COLUMN_ID = 0;
	public static final int COLUMN_PROFILE_NAME = 1;
	public static final int COLUMN_PROFILE_STATE = 2;
	public static final int COLUMN_WORLD_WIDTH = 3;
	public static final int COLUMN_WORLD_HEIGHT = 4;
	public static final int COLUMN_WORLD_WRAP_X = 5;
	public static final int COLUMN_WORLD_WRAP_Y = 6;
	public static final int COLUMN_ISLAND_VIEW = 7;
	public static final int COLUMN_MAXIMUM_TURNS = 8;
	public static final int COLUMN_TURN_INTERVAL = 9;
	public static final int COLUMN_ISLAND_COUNT = 10;
	public static final int COLUMN_ISLAND_SPACING = 11;
	public static final ProfileState DEFAULT_PROFILE_STATE = ProfileState.UNINITIALIZED;
	public static final Integer DEFAULT_WORLD_WIDTH = 1000;
	public static final Integer DEFAULT_WORLD_HEIGHT = 1000;
	public static final Boolean DEFAULT_WORLD_WRAP_X = true;
	public static final Boolean DEFAULT_WORLD_WRAP_Y = true;
	private static final Long DEFAULT_ID = null;
	private static final String DEFAULT_PROFILE_NAME = null;
	private Long id;
	private String profileName;
	private ProfileState profileState = DEFAULT_PROFILE_STATE;
	private Integer worldWidth = getDefaultWorldWidth();
	private Integer worldHeight = getDefaultWorldHeight();
	private Boolean worldWrapX = getDefaultWorldWrapX();
	private Boolean worldWrapY = getDefaultWorldWrapY();
	private Integer islandView = getDefaultIslandView();
	private Integer maximumTurns = getDefaultMaximumTurns();
	private Integer turnInterval = getDefaultTurnInterval();
	private Integer islandCount = getDefaultIslandCount();
	private Integer islandSpacing = getDefaultIslandSpacing();
	private static final Integer MINIMUM_WORLD_WIDTH = 500;
	private static final Integer MAXIMUM_WORLD_WIDTH = 2000;
	private static final Integer MINIMUM_WORLD_HEIGHT = 500;
	private static final Integer MAXIMUM_WORLD_HEIGHT = 2000;
	private static final Integer DEFAULT_ISLAND_COUNT = 1000;
	private static final Integer MINIMUM_ISLAND_COUNT = 500;
	private static final Integer MAXIMUM_ISLAND_COUNT = 2000;
	private static final Integer DEFAULT_ISLAND_SPACING = 10;
	private static final Integer MINIMUM_ISLAND_SPACING = 5;
	private static final Integer MAXIMUM_ISLAND_SPACING = 20;
	private static final Integer DEFAULT_ISLAND_VIEW = 10;
	private static final Integer MINIMUM_ISLAND_VIEW = 5;
	private static final Integer MAXIMUM_ISLAND_VIEW = 20;
	private static final Integer DEFAULT_MAXIMUM_TURNS = 200;
	private static final Integer MINIMUM_MAXIMUM_TURNS = 100;
	private static final Integer MAXIMUM_MAXIMUM_TURNS = 500;
	private static final Integer DEFAULT_TURN_INTERVAL = 360;
	private static final Integer MINIMUM_TURN_INTERVAL = 180;
	private static final Integer MAXIMUM_TURN_INTERVAL = 720;
	private static final int GENERATOR_INITIAL_VALUE = 0;
	private static final int GENERATOR_MAXIMUM_VALUE = 1000;
	public static Integer getMinimumWorldWidth(){
		return MINIMUM_WORLD_WIDTH;
	}
	public static Integer getMaximumWorldWidth(){
		return MAXIMUM_WORLD_WIDTH;
	}
	public static Integer getMinimumWorldHeight(){
		return MINIMUM_WORLD_HEIGHT;
	}
	public static Integer getMaximumWorldHeight(){
		return MAXIMUM_WORLD_HEIGHT;
	}
	public static Integer getDefaultIslandCount(){
		return DEFAULT_ISLAND_COUNT;
	}
	public static Integer getMinimumIslandCount(){
		return MINIMUM_ISLAND_COUNT;
	}
	public static Integer getMaximumIslandCount(){
		return MAXIMUM_ISLAND_COUNT;
	}
	public static Integer getDefaultIslandSpacing(){
		return DEFAULT_ISLAND_SPACING;
	}
	public static Integer getMinimumIslandSpacing(){
		return MINIMUM_ISLAND_SPACING;
	}
	public static Integer getMaximumIslandSpacing(){
		return MAXIMUM_ISLAND_SPACING;
	}
	public static Integer getDefaultIslandView(){
		return DEFAULT_ISLAND_VIEW;
	}
	public static Integer getMinimumIslandView(){
		return MINIMUM_ISLAND_VIEW;
	}
	public static Integer getMaximumIslandView(){
		return MAXIMUM_ISLAND_VIEW;
	}
	public static Integer getDefaultMaximumTurns() {
		return DEFAULT_MAXIMUM_TURNS;
	}
	public static Integer getMinimumMaximumTurns() {
		return MINIMUM_MAXIMUM_TURNS;
	}
	public static Integer getMaximumMaximumTurns() {
		return MAXIMUM_MAXIMUM_TURNS;
	}
	public static Integer getDefaultTurnInterval() {
		return DEFAULT_TURN_INTERVAL;
	}
	public static Integer getMinimumTurnInterval() {
		return MINIMUM_TURN_INTERVAL;
	}
	public static Integer getMaximumTurnInterval() {
		return MAXIMUM_TURN_INTERVAL;
	}
	public Profile(String theProfileName){
		setId(null);
		setProfileName(theProfileName);
	}
	public static Integer getDefaultWorldWidth() {
		return DEFAULT_WORLD_WIDTH;
	}
	public static Integer getDefaultWorldHeight() {
		return DEFAULT_WORLD_HEIGHT;
	}
	public static Boolean getDefaultWorldWrapX() {
		return DEFAULT_WORLD_WRAP_X;
	}
	public static Boolean getDefaultWorldWrapY() {
		return DEFAULT_WORLD_WRAP_Y;
	}
	public Profile(Cursor theCursor){
		try{
			setId(theCursor.getLong(COLUMN_ID));
		}catch(Exception e){
			e.printStackTrace();
			setId(DEFAULT_ID);
		}
		try{
			setProfileName(theCursor.getString(COLUMN_PROFILE_NAME));
		}catch(Exception e){
			e.printStackTrace();
			setProfileName(DEFAULT_PROFILE_NAME);
		}
		try{
			setProfileState(ProfileState.valueOf(theCursor.getString(COLUMN_PROFILE_STATE)));
		}catch(Exception e){
			e.printStackTrace();
			setProfileState(DEFAULT_PROFILE_STATE);
		}
		try{
			setProfileState(ProfileState.valueOf(theCursor.getString(COLUMN_PROFILE_STATE)));
		}catch(Exception e){
			e.printStackTrace();
			setProfileState(DEFAULT_PROFILE_STATE);
		}
		try{
			setWorldWidth(theCursor.getInt(COLUMN_WORLD_WIDTH));
		}catch(Exception e){
			e.printStackTrace();
			setWorldWidth(getDefaultWorldWidth());
		}
		try{
			setWorldHeight(theCursor.getInt(COLUMN_WORLD_HEIGHT));
		}catch(Exception e){
			e.printStackTrace();
			setWorldHeight(getDefaultWorldHeight());
		}
		try{
			setWorldWrapX(Boolean.parseBoolean(theCursor.getString(COLUMN_WORLD_WRAP_X)));
		}catch(Exception e){
			e.printStackTrace();
			setWorldWrapX(getDefaultWorldWrapX());
		}
		try{
			setWorldWrapY(Boolean.parseBoolean(theCursor.getString(COLUMN_WORLD_WRAP_Y)));
		}catch(Exception e){
			e.printStackTrace();
			setWorldWrapY(getDefaultWorldWrapY());
		}
		try{
			setIslandView(theCursor.getInt(COLUMN_ISLAND_VIEW));
		}catch(Exception e){
			e.printStackTrace();
			setIslandView(getDefaultIslandView());
		}
		try{
			setMaximumTurns(theCursor.getInt(COLUMN_MAXIMUM_TURNS));
		}catch(Exception e){
			e.printStackTrace();
			setMaximumTurns(getDefaultMaximumTurns());
		}
		try{
			setTurnInterval(theCursor.getInt(COLUMN_TURN_INTERVAL));
		}catch(Exception e){
			e.printStackTrace();
			setTurnInterval(getDefaultTurnInterval());
		}
		try{
			setIslandCount(theCursor.getInt(COLUMN_ISLAND_COUNT));
		}catch(Exception e){
			e.printStackTrace();
			setIslandCount(getDefaultIslandCount());
		}
		try{
			setIslandSpacing(theCursor.getInt(COLUMN_ISLAND_SPACING));
		}catch(Exception e){
			e.printStackTrace();
			setIslandSpacing(getDefaultIslandSpacing());
		}
	}
	
	public Long getId() {
		return id;
	}
	private void setId(Long id) {
		this.id = id;
	}
	public String getProfileName() {
		return profileName;
	}
	public void setProfileName(String theProfileName) {
		this.profileName = theProfileName;
	}
	@Override
	public String toString(){
		return getProfileName();
	}
	public ProfileState getProfileState() {
		return profileState;
	}
	public void setProfileState(ProfileState profileState) {
		this.profileState = profileState;
	}
	public Integer getWorldWidth() {
		return worldWidth;
	}
	public void setWorldWidth(Integer worldWidth) {
		this.worldWidth = worldWidth;
	}
	public Integer getWorldHeight() {
		return worldHeight;
	}
	public void setWorldHeight(Integer worldHeight) {
		this.worldHeight = worldHeight;
	}
	public Boolean getWorldWrapX() {
		return worldWrapX;
	}
	public void setWorldWrapX(Boolean worldWrapX) {
		this.worldWrapX = worldWrapX;
	}
	public Boolean getWorldWrapY() {
		return worldWrapY;
	}
	public void setWorldWrapY(Boolean worldWrapY) {
		this.worldWrapY = worldWrapY;
	}
	public Integer getIslandView() {
		return islandView;
	}
	public void setIslandView(Integer islandView) {
		this.islandView = islandView;
	}
	public Integer getMaximumTurns() {
		return maximumTurns;
	}
	public void setMaximumTurns(Integer maximumTurns) {
		this.maximumTurns = maximumTurns;
	}
	public Integer getTurnInterval() {
		return turnInterval;
	}
	public void setTurnInterval(Integer turnInterval) {
		this.turnInterval = turnInterval;
	}
	public WorldPosition generateIslandPosition(List<WorldPosition> thePositions,Integer theIslandSpacing,Random theRandom) throws IslandPositionGenerationException{
		WorldPosition theCandidate = null;
		int theCounter = GENERATOR_INITIAL_VALUE;
		boolean done = false;
		do{
			theCandidate = new WorldPosition(theRandom.nextDouble()*getWorldWidth(),theRandom.nextDouble()*getWorldHeight());
			double theMinimumDistance = Double.MAX_VALUE;
			for(WorldPosition thePosition:thePositions){
				double theDistance = thePosition.getWorldShapeDistance(theCandidate, this);
				if(theDistance<theMinimumDistance){
					theMinimumDistance=theDistance;
				}
				if(theMinimumDistance<theIslandSpacing){
					theCounter++;
					break;
				}
			}
			if(theCounter>GENERATOR_MAXIMUM_VALUE){
				throw new IslandPositionGenerationException();
			}
			if(theMinimumDistance>=theIslandSpacing){
				done = true;
			}
		}while(!done);
		return theCandidate;
	}
	public void generateIslandPositions(List<WorldPosition> thePositions,Integer theIslandCount,
			Integer theIslandSpacing,Random theRandom,int theCount) throws IslandPositionGenerationException {
		while(theCount>0 && thePositions.size()<theIslandCount){
			thePositions.add(generateIslandPosition(thePositions,theIslandSpacing,theRandom));
			theCount--;
		}
	}
	public Integer getIslandCount() {
		return islandCount;
	}
	public void setIslandCount(Integer islandCount) {
		this.islandCount = islandCount;
	}
	public Integer getIslandSpacing() {
		return islandSpacing;
	}
	public void setIslandSpacing(Integer islandSpacing) {
		this.islandSpacing = islandSpacing;
	}
}
